<?php

use \Phalcon\Config\Adapter\Ini,
    \Phalcon\Mvc\Router,
    \Phalcon\Mvc\View,
    \Phalcon\Mvc\View\Engine\Volt,
    \Phalcon\Mvc\Dispatcher,
    \Phalcon\Events\Manager as EventsManager,
    \Phalcon\Db\Profiler,
    \Phalcon\Session\Adapter\Files as Session,
    \Phalcon\Mvc\Model\Metadata\Files as MetaDataAdapter,
    \Phalcon\Mvc\Application,
    \Phalcon\DI\FactoryDefault;

if ( PHP_OS == 'WINNT' ) define( 'NL', "\r\n" );
else define( 'NL', "\n" );
define( 'BL', "<br />" . NL );

$config = new Ini( ROOT_CONFIG . 'site.ini' );

if ( $config->application->debug ) {
    ini_set( 'display_errors', 1 );
    error_reporting( -1 );
}

$di      = new FactoryDefault();
$modules = [ ];

$di->set( 'mvc', function () {
    return new Ini( ROOT_CONFIG . 'mvc.ini' );
}, true );

$di->set( 'url', function () use ( $config ) {
    $url = new Url;
    $url->setBaseUri( $config->application->viewsDir );

    return $url;
} );

foreach ( $di->getMvc()->toArray() as $idx => $item ) {
    if ( array_key_exists( 'moduleName', $item ) ) {
        $modules[ $idx ]['className'] = 'MVC\\' . ucfirst( $item['moduleName'] ) . '\\Module';
        $modules[ $idx ]['path']      = ROOT_APP . $item['moduleName'] . DS . $item['moduleDir'];
        if ( isset( $item['router'] ) )
            $modules[ $idx ]['router'] = ROOT_APP . $item['moduleName'] . DS . $item['router'];
    }
}

$di->set( 'router', function () use ( $config, $modules ) {
    $router = new Router( false );
    $router->removeExtraSlashes( true );
    $router->setDefaultModule( $config->application->defaultModule );
    foreach ( $modules as $module )
        if ( isset( $module['router'] ) && is_file( $module['router'] ) ) require $module['router'];
    require ROOT . $config->application->router;

    return $router;
} );

$di->set( 'dispatcher', function () use ( $config ) {
    $dispatcher = new Dispatcher();
    $dispatcher->setDefaultNamespace( $config->application->defaultNamespace );

    $eventsManager = new EventsManager;
    $eventsManager->attach( "dispatch", function ( $event, $dispatcher, $exception ) use ( $config ) {
        if ( !$config->application->debug ) {
            if ( $event->getType() == 'beforeException' ) {
                exit( '系统出错了' );
            }
        }
    } );

    $dispatcher->setEventsManager( $eventsManager );

    return $dispatcher;
} );

$di->set( 'view', function () {
    $view = new View;
    $view->registerEngines( [ '.volt' => 'volt' ] );

    return $view;
}, true );

$di->set( 'volt', function () use ( $config, $di ) {
    $volt = new Volt( $di->getView(), $di );
    $volt->setOptions( [
        'compiledPath'      => ROOT . $config->cache->compiledDir,
        'compiledExtension' => $config->cache->compiledExtension,
        'compiledSeparator' => $config->cache->compiledSeparator,
        'compileAlways'     => (bool)( $config->cache->compileAlways )
    ] );

    $compiler = $volt->getCompiler();

    foreach ( explode( ',', $config->function->compiler ) as $func ) {
        if ( is_string( $func ) ) $compiler->addFunction( $func, $func );
        else throw new Exception( 'load function error' );
    }

    return $volt;
}, true );

$di->set( 'modelsMetadata', function () use ( $config ) {
    return new MetaDataAdapter( [
        'metaDataDir' => $config->cache->metaData
    ] );
} );

$di->set( 'profiler', function () {
    return new Profiler;
}, true );

$di->set( 'db', function () use ( $config, $di ) {
    $eventsManager = new EventsManager;
    $profiler      = $di->getProfiler();
    $eventsManager->attach( 'db', function ( $event, $connection ) use ( $profiler ) {
        if ( $event->getType() == 'beforeQuery' ) {
            $profiler->startProfile( $connection->getSQLStatement() );
        }
        if ( $event->getType() == 'afterQuery' ) {
            $profiler->stopProfile();
        }
    } );
    $dbclass = sprintf( '\Phalcon\Db\Adapter\Pdo\%s', $config->database->adapter );

    $connection = new $dbclass( [
        'host'     => $config->database->host,
        'dbname'   => $config->database->dbname,
        'port'     => $config->database->port,
        'username' => $config->database->username,
        'password' => $config->database->password
    ] );

    $connection->setEventsManager( $eventsManager );

    return $connection;
}, true );

$di->set( 'session', function () {
    $session = new Session;
    $session->start();

    return $session;
} );

try {

    $application = new Application( $di );

    $application->registerModules( $modules );

    unset( $modules );

    return $application->handle()->getContent();

} catch ( \Exception $e ) {
    return $e->getMessage();
}